Presentation des résultats de l’analyse RFM
Tres bon clients
RFM=na.omit(tbl_df(read.csv(file="r_ANALYSE_RFM2016.csv",header = T,sep=';')))
RFM2=read.csv(file="r_ANALYSE_RFM2016.csv",header = T,sep=';')
tres_bon=filter(RFM2,TYPO=='01_TRES_BONS')
head(tres_bon)
CA
# General CA
CA <- sum(na.omit(RFM2$MONTANT_CUMULE))
paste("CA :",CA)
# Tres bon clients CA
CATB <- sum(tres_bon$MONTANT_CUMULE)
paste("CA Tres bon clients:",CATB)
paste("Tres bon clients CA proportion:",round(CATB/CA,2)*100,"%")
New <- filter(RFM2, TYPO=='06_NOUVEAUX')
NewCa <- sum(New$MONTANT_CUMULE)
paste("CA Nouveaux clients :", NewCa)
paste("Nouveaux clients CA proportion:",round(NewCa/CA,2)*100,"%")
Clients : type classique
Âge
## presentation client âge moyen/ localisation client / depense moyenne par visite et sur la periode
# moyen âge
age=RFM2$AGE
age_moyen=mean(age,na.rm = T)
ageTB=tres_bon$AGE
paste("Age moyen de tout les clients :",round(age_moyen,0))
age_moyenTB=mean(ageTB, na.r = T)
paste("Age moyen des Tres bon clients :",round(age_moyenTB,0))
paste("Difference Age moyen des Tres bon clients par raport à toute la clientele :",round(age_moyenTB-age_moyen,3))
Pas de conclusion pertinantes.
Nombre de visites
# nb visite
nb_visites_moyenne <- mean(RFM2$NB_VISITE,na.rm = T)
paste("Nmb de visites en moyenne de tout les clients :",round(nb_visites_moyenne,1))
nb_visites_moyenneTB <- mean(tres_bon$NB_VISITE, na.rm = T)
paste("Nmb de visites en moyenne des Tres bon clients :",round(nb_visites_moyenneTB,1))
paste("Difference de la moyenne du nmb de visites des Tres bon clients par raport à toute la clientele :",round(nb_visites_moyenneTB-nb_visites_moyenne,1))
Comme prévu: les très bon clients visites plus les magasins.
Nombre d cadeaux
nb_cadeau_moyenne <- mean(RFM2$NB_CADEAUX, na.rm = T)
paste("Nmb de caeaux en moyenne de tout les clients :",round(nb_cadeau_moyenne,1))
nb_cadeau_moyenneTB <- mean(tres_bon$NB_CADEAUX, na.rm = T)
paste("Nmb de cadeaux en moyenne des Tres bon clients :",round(nb_cadeau_moyenneTB,1))
paste("Difference de la moyenne du nmb de cadeaux des Tres bon clients par raport à toute la clientele :",round(nb_cadeau_moyenneTB-nb_cadeau_moyenne,1))
Comme prévu: les très bon clients reçoivent plus de cadeaux.
Localisation client
# localisation client
table(na.omit(RFM2$REGIONS))
paste(round(1035/3250,2)*100,"%")
table(tres_bon$REGIONS)
library(ggplot2)
localisation=ggplot(data = RFM2)+aes(x=REGIONS, fill=REGIONS)+geom_bar()
localisation+scale_fill_manual(values=c("#E69F00", "#56B4E9"))+labs(title="Répartition des clients par région", x="Régions", y="Effectif")
localisationTB=ggplot(data = tres_bon)+aes(x=REGIONS, fill=REGIONS)+geom_bar()
localisationTB+scale_fill_manual(values=c("#E69F00", "#56B4E9"))+labs(title="Répartition des très bon clients par région", x="Régions", y="Effectif")
Quasiment un tiers des clients sont situé sur Paris.
Dépenses moyennes
Moyenne
# depense moyenne par visite 117€
CA_moyenne <- mean(RFM2$CA_MOY_VISITE,na.rm = T)
CA_moyenne
CA_moyenneTB <- mean(tres_bon$CA_MOY_VISITE, na.rm = T)
CA_moyenneTB
CA_moyenneTB-CA_moyenne
Periodique
# depense moyenne sur la periode
mt_moyenne <- mean(RFM$MONTANT_CUMULE,na.rm = T)
mt_moyenne
mt_moyenneTB <- mean(tres_bon$MONTANT_CUMULE,na.rm = T)
mt_moyenneTB
mt_moyenneTB-mt_moyenne
Les très bon cients cumulent plus de dépenses malgré des dépenses inférieures à la moyenne par passage (car plus de passage en tout).
Age
# depense moyenne sur la periode en fonction de l'age
tab=data.frame(RFM2$AGE,RFM2$MONTANT_CUMULE)
tab=na.omit(tab)
tabTB=data.frame(tres_bon$AGE,tres_bon$MONTANT_CUMULE)
tabTB=na.omit(tabTB)
groupe_age=cut(tab$RFM2.AGE,breaks = c(0,15,20,25,30,35,40,45,50,55,60,65,70,75,90))
groupe_ageTB=cut(tabTB$tres_bon.AGE,breaks = c(0,15,20,25,30,35,40,45,50,55,60,65,70,75,90))
tab=data.frame(tab,groupe_age)
tabTB=data.frame(tabTB, groupe_ageTB)
names(tab)=c('age','montant_cumule',"Intervalle_age")
names(tabTB)=c('age','montant_cumule',"Intervalle_age")
summary(tabTB$Intervalle_age)
T40_50=filter(tab,Intervalle_age=="(40,45]")
sum(T40_50$montant_cumule)
ggplot(tab)+aes(x=Intervalle_age,col=montant_cumule, fill=Intervalle_age)+geom_bar()+labs(title="Repartition du CA par groupe d'age", x="age", y="Effectif")
ggplot(tabTB)+aes(x=Intervalle_age,col=montant_cumule, fill=Intervalle_age)+geom_bar()+labs(title="Repartition des tres bon clients par groupe d'age", x="age", y="Effectif")
ggplot(data=RFM2, aes(x=TYPO, y=MONTANT_CUMULE, fill=TYPO)) +
geom_bar(aes(y = (..count..)/sum(..count..), stat="identity"))+
scale_fill_brewer(palette="Spectral")+
labs(x="Typologies", y="CA", title="Répartion du CA")
summary(tab)
summary(tabTB)
Localisation - graphs
#localisation
summary(RFM$REGIONS)
Paris Province
5465 9886
11840/(24113+11840)
[1] 0.3293188
24113/(24113+11840)
[1] 0.6706812
980/(980+2053)
[1] 0.3231124
2053/(980+2053)
[1] 0.6768876
#35955 clients, 3253 tres bon
typo<- ggplot(RFM2) +
aes(x=TYPO,col=TYPO, fill=TYPO) +
geom_bar(aes(y = (..count..)/sum(..count..),fill=TYPO))
typo +
scale_color_brewer(palette="Spectral") +
scale_fill_brewer(palette="Spectral") +
labs(y="Proportion", x="Typologie", title="Repartition des clients apres RFM") #+

#geom_text(aes(label=len), vjust=1.6, color="white", size=3.5)
summary(RFM2$TYPO)
01_TRES_BONS 02_BONS 03_PERTES 04_PETITS 05_FAIBLES 06_NOUVEAUX 07_INACTIFS
3250 796 866 980 1829 8745 19489
ggplot(data=RFM2, aes(x=TYPO, y=MONTANT_CUMULE, fill=TYPO)) +
geom_bar(stat="identity")+
scale_fill_brewer(palette="Spectral")+
labs(x="Typologies", y="CA", title="Répartion du CA")

3250+796+866+980+1829+8745+19489
[1] 35955
3250/35955
[1] 0.09039077
796/35955
[1] 0.02213878
866/35955
[1] 0.02408566
980/35955
[1] 0.02725629
1928/35955
[1] 0.05362258
8745/35955
[1] 0.2432207
19489/35955
[1] 0.5420387
9.1+2.2+2.4+2.3+5.4+24.4+54.2
[1] 100
#install.packages("plotrix")
library(plotrix)
TypoC <- RFM2%>% select(TYPO)
summary(TypoC)
TYPO
01_TRES_BONS: 3250
02_BONS : 796
03_PERTES : 866
04_PETITS : 980
05_FAIBLES : 1829
06_NOUVEAUX : 8745
07_INACTIFS :19489
x=c(3250, 796, 866, 980, 1829, 8745, 19489)
tot <- 3250+796+980+1829+8745+19489
3250/tot
[1] 0.09262162
796/tot
[1] 0.02268517
866/tot
[1] 0.0246801
980/tot
[1] 0.02792898
1829/tot
[1] 0.0521246
8745/tot
[1] 0.2492234
19489/tot
[1] 0.5554162
9.26+2.26+2.46+2.79+5.21+24.92+55.54
[1] 102.44
lbls <- c("TRES BONS","BONS","PERTES","PETITS","FAIBLES","NOUVEAUX","INACTIFS")
pie3D(x, labels=lbls, explode=0.1, main="Typologies des clients", col = c("red", "darkgoldenrod3", "darkgoldenrod1", "yellow", "yellowgreen", "seagreen4", "royalblue4"))

## stat bi-variées
Client type Tres Bon
Age
age=tres_bon$AGE
mean(age,na.rm = T)
[1] 46.29013
Localisation
# localisation client
table(tres_bon$REGIONS)
Paris Province
1035 2215
ggplot(data = tres_bon)+aes(x=REGIONS)+geom_bar()

Depense Moyenne
Par Visite
# depense moyenne par visite 117€
mean(tres_bon$CA_MOY_VISITE,na.rm = T)
[1] 96.07324
Periodique
# depense moyenne sur la periode
paste("Montant cumule:",round(mean(tres_bon$MONTANT_CUMULE,na.rm = T),2))
[1] "Montant cumule: 712.94"
paste("Nmb de visite:",round(mean(tres_bon$NB_VISITE,na.rm = T),0))
[1] "Nmb de visite: 8"
paste("Depense moyenne par visite:", round(mean(tres_bon$MONTANT_CUMULE,na.rm = T)/mean(tres_bon$NB_VISITE,na.rm = T),2))
[1] "Depense moyenne par visite: 89.5"
ggplot(RFM2)+aes(x=TYPO,col=TYPO)+geom_bar(aes(y = (..count..)/sum(..count..),fill=TYPO))+xlab("typologie")+ylab("proportion")

Plo_ly
#install.packages('Plot_ly')
library(plotly)
Typo=unique(RFM2$TYPO)
Typo
[1] 01_TRES_BONS 07_INACTIFS 03_PERTES 05_FAIBLES 02_BONS 04_PETITS 06_NOUVEAUX
Levels: 01_TRES_BONS 02_BONS 03_PERTES 04_PETITS 05_FAIBLES 06_NOUVEAUX 07_INACTIFS
df=data.frame()
df_final=data.frame()
for (i in Typo){
df=RFM2%>% filter(TYPO==i) %>% summarise(moy_Montant_Cumule=mean(MONTANT_CUMULE,na.rm=T),
moy_NB_Visite=mean(NB_VISITE,na.rm=T),
moy_Recence=mean(RECENCE,na.rm=T))
df_final=rbind(df_final,df)
}
df_final=cbind(Typo,df_final)
Typo3D <- plot_ly(data=df_final,x=~moy_Montant_Cumule,
y=~moy_NB_Visite,z=~moy_Recence,
color=df_final$Typo, colors = c("red", "darkgoldenrod3", "darkgoldenrod1", "yellow", "yellowgreen", "seagreen4", "royalblue4" ))
Typo3D
Typo3D_TB <- plot_ly(data=df_final,x=~moy_Montant_Cumule,
y=~moy_NB_Visite,z=~moy_Recence,
color=df_final$Typo, colors = c("red", "darkgray", "darkgray", "darkgray", "darkgray", "darkgray", "darkgray" ))
Typo3D_TB
LS0tDQp0aXRsZTogIlJGTSAyMDE2IC0gVHJlcyBib24gY2xpZW50cyINCmF1dGhvcjogIkphbiBNYWxpayINCmRhdGU6ICIxNSBNYXJjaCAyMDE4Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KPiBBcGFydGUNCg0KDQogICogQmVsbGVzIGNvdWxldXJzIDogKnNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjOTk5OTk5IiwgIiNFNjlGMDAiLCAiIzU2QjRFOSIpKSoNCiAgKiBDb250ZXh0ZSAmIG9iamVjdGlmcw0KICAqIFByZXNlbnRhdGlvbiBlbnRyZXByaXNlICsgb2JqZWN0aWZzIHNlZ21lbnRhdGlvbnMNCg0KIyBJbXBvcnQgUGFja2FnZXMNCg0KYGBge3J9DQojIyByZXN1bHRhdCBwb3VyIG5vdHJlIGdyb3VwZSB0cmVzIGJvbg0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCiMgSW5zdGFsbGVyDQojaW5zdGFsbC5wYWNrYWdlcygid2VzYW5kZXJzb24iKQ0KIyBCZWxsZXMgY291bGV1cnMNCmxpYnJhcnkod2VzYW5kZXJzb24pDQpgYGANCg0KDQojIFByZXNlbnRhdGlvbiBkZXMgcsOpc3VsdGF0cyBkZSBsJ2FuYWx5c2UgUkZNDQoNCiMjIFRyZXMgYm9uIGNsaWVudHMNCmBgYHtyfQ0KUkZNPW5hLm9taXQodGJsX2RmKHJlYWQuY3N2KGZpbGU9InJfQU5BTFlTRV9SRk0yMDE2LmNzdiIsaGVhZGVyID0gVCxzZXA9JzsnKSkpDQpSRk0yPXJlYWQuY3N2KGZpbGU9InJfQU5BTFlTRV9SRk0yMDE2LmNzdiIsaGVhZGVyID0gVCxzZXA9JzsnKQ0KdHJlc19ib249ZmlsdGVyKFJGTTIsVFlQTz09JzAxX1RSRVNfQk9OUycpDQpoZWFkKHRyZXNfYm9uKQ0KYGBgDQoNCiMjIENBDQoNCmBgYHtyfQ0KIyBHZW5lcmFsIENBDQpDQSA8LSBzdW0obmEub21pdChSRk0yJE1PTlRBTlRfQ1VNVUxFKSkNCnBhc3RlKCJDQSA6IixDQSkNCg0KIyBUcmVzIGJvbiBjbGllbnRzIENBDQpDQVRCIDwtIHN1bSh0cmVzX2JvbiRNT05UQU5UX0NVTVVMRSkNCnBhc3RlKCJDQSBUcmVzIGJvbiBjbGllbnRzOiIsQ0FUQikNCg0KcGFzdGUoIlRyZXMgYm9uIGNsaWVudHMgQ0EgcHJvcG9ydGlvbjoiLHJvdW5kKENBVEIvQ0EsMikqMTAwLCIlIikNCg0KTmV3IDwtIGZpbHRlcihSRk0yLCBUWVBPPT0nMDZfTk9VVkVBVVgnKQ0KTmV3Q2EgPC0gc3VtKE5ldyRNT05UQU5UX0NVTVVMRSkNCnBhc3RlKCJDQSBOb3V2ZWF1eCBjbGllbnRzIDoiLCBOZXdDYSkNCg0KcGFzdGUoIk5vdXZlYXV4IGNsaWVudHMgQ0EgcHJvcG9ydGlvbjoiLHJvdW5kKE5ld0NhL0NBLDIpKjEwMCwiJSIpDQpgYGANCg0KIyBDbGllbnRzIDogdHlwZSBjbGFzc2lxdWUNCg0KIyMgw4JnZQ0KDQpgYGB7cn0NCiMjIHByZXNlbnRhdGlvbiBjbGllbnQgw6JnZSBtb3llbi8gbG9jYWxpc2F0aW9uIGNsaWVudCAvIGRlcGVuc2UgbW95ZW5uZSBwYXIgdmlzaXRlIGV0IHN1ciBsYSBwZXJpb2RlDQojIG1veWVuIMOiZ2UNCmFnZT1SRk0yJEFHRQ0KYWdlX21veWVuPW1lYW4oYWdlLG5hLnJtID0gVCkNCmFnZVRCPXRyZXNfYm9uJEFHRQ0KcGFzdGUoIkFnZSBtb3llbiBkZSB0b3V0IGxlcyBjbGllbnRzIDoiLHJvdW5kKGFnZV9tb3llbiwwKSkNCmFnZV9tb3llblRCPW1lYW4oYWdlVEIsIG5hLnIgPSBUKQ0KcGFzdGUoIkFnZSBtb3llbiBkZXMgVHJlcyBib24gY2xpZW50cyA6Iixyb3VuZChhZ2VfbW95ZW5UQiwwKSkNCnBhc3RlKCJEaWZmZXJlbmNlIEFnZSBtb3llbiBkZXMgVHJlcyBib24gY2xpZW50cyBwYXIgcmFwb3J0IMOgIHRvdXRlIGxhIGNsaWVudGVsZSA6Iixyb3VuZChhZ2VfbW95ZW5UQi1hZ2VfbW95ZW4sMykpDQpgYGANCg0KUGFzIGRlIGNvbmNsdXNpb24gcGVydGluYW50ZXMuDQoNCiMjIE5vbWJyZSBkZSB2aXNpdGVzDQoNCmBgYHtyfQ0KIyBuYiB2aXNpdGUNCm5iX3Zpc2l0ZXNfbW95ZW5uZSA8LSBtZWFuKFJGTTIkTkJfVklTSVRFLG5hLnJtID0gVCkNCnBhc3RlKCJObWIgZGUgdmlzaXRlcyBlbiBtb3llbm5lIGRlIHRvdXQgbGVzIGNsaWVudHMgOiIscm91bmQobmJfdmlzaXRlc19tb3llbm5lLDEpKQ0KbmJfdmlzaXRlc19tb3llbm5lVEIgPC0gbWVhbih0cmVzX2JvbiROQl9WSVNJVEUsIG5hLnJtID0gVCkNCnBhc3RlKCJObWIgZGUgdmlzaXRlcyBlbiBtb3llbm5lIGRlcyBUcmVzIGJvbiBjbGllbnRzIDoiLHJvdW5kKG5iX3Zpc2l0ZXNfbW95ZW5uZVRCLDEpKQ0KcGFzdGUoIkRpZmZlcmVuY2UgZGUgbGEgbW95ZW5uZSBkdSBubWIgZGUgdmlzaXRlcyBkZXMgVHJlcyBib24gY2xpZW50cyBwYXIgcmFwb3J0IMOgIHRvdXRlIGxhIGNsaWVudGVsZSA6Iixyb3VuZChuYl92aXNpdGVzX21veWVubmVUQi1uYl92aXNpdGVzX21veWVubmUsMSkpDQpgYGANCg0KQ29tbWUgcHLDqXZ1OiBsZXMgdHLDqHMgYm9uIGNsaWVudHMgdmlzaXRlcyBwbHVzIGxlcyBtYWdhc2lucy4NCg0KIyMgTm9tYnJlIGQgY2FkZWF1eA0KDQpgYGB7cn0NCm5iX2NhZGVhdV9tb3llbm5lIDwtIG1lYW4oUkZNMiROQl9DQURFQVVYLCBuYS5ybSA9IFQpDQpwYXN0ZSgiTm1iIGRlIGNhZWF1eCBlbiBtb3llbm5lIGRlIHRvdXQgbGVzIGNsaWVudHMgOiIscm91bmQobmJfY2FkZWF1X21veWVubmUsMSkpDQpuYl9jYWRlYXVfbW95ZW5uZVRCIDwtIG1lYW4odHJlc19ib24kTkJfQ0FERUFVWCwgbmEucm0gPSBUKQ0KcGFzdGUoIk5tYiBkZSBjYWRlYXV4IGVuIG1veWVubmUgZGVzIFRyZXMgYm9uIGNsaWVudHMgOiIscm91bmQobmJfY2FkZWF1X21veWVubmVUQiwxKSkNCnBhc3RlKCJEaWZmZXJlbmNlIGRlIGxhIG1veWVubmUgZHUgbm1iIGRlIGNhZGVhdXggZGVzIFRyZXMgYm9uIGNsaWVudHMgcGFyIHJhcG9ydCDDoCB0b3V0ZSBsYSBjbGllbnRlbGUgOiIscm91bmQobmJfY2FkZWF1X21veWVubmVUQi1uYl9jYWRlYXVfbW95ZW5uZSwxKSkNCmBgYA0KDQpDb21tZSBwcsOpdnU6IGxlcyB0csOocyBib24gY2xpZW50cyByZcOnb2l2ZW50IHBsdXMgZGUgY2FkZWF1eC4NCg0KIyMgTG9jYWxpc2F0aW9uIGNsaWVudA0KDQpgYGB7cn0NCiMgbG9jYWxpc2F0aW9uIGNsaWVudA0KdGFibGUobmEub21pdChSRk0yJFJFR0lPTlMpKQ0KcGFzdGUocm91bmQoMTAzNS8zMjUwLDIpKjEwMCwiJSIpDQp0YWJsZSh0cmVzX2JvbiRSRUdJT05TKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbG9jYWxpc2F0aW9uPWdncGxvdChkYXRhID0gUkZNMikrYWVzKHg9UkVHSU9OUywgZmlsbD1SRUdJT05TKStnZW9tX2JhcigpDQpsb2NhbGlzYXRpb24rc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiNFNjlGMDAiLCAiIzU2QjRFOSIpKStsYWJzKHRpdGxlPSJSw6lwYXJ0aXRpb24gZGVzIGNsaWVudHMgcGFyIHLDqWdpb24iLCB4PSJSw6lnaW9ucyIsIHk9IkVmZmVjdGlmIikNCmxvY2FsaXNhdGlvblRCPWdncGxvdChkYXRhID0gdHJlc19ib24pK2Flcyh4PVJFR0lPTlMsIGZpbGw9UkVHSU9OUykrZ2VvbV9iYXIoKQ0KbG9jYWxpc2F0aW9uVEIrc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiNFNjlGMDAiLCAiIzU2QjRFOSIpKStsYWJzKHRpdGxlPSJSw6lwYXJ0aXRpb24gZGVzIHRyw6hzIGJvbiBjbGllbnRzIHBhciByw6lnaW9uIiwgeD0iUsOpZ2lvbnMiLCB5PSJFZmZlY3RpZiIpDQpgYGANCiBRdWFzaW1lbnQgdW4gdGllcnMgZGVzIGNsaWVudHMgc29udCBzaXR1w6kgc3VyIFBhcmlzLg0KDQojIyBEw6lwZW5zZXMgbW95ZW5uZXMNCg0KIyMjIE1veWVubmUNCg0KYGBge3J9DQojIGRlcGVuc2UgbW95ZW5uZSBwYXIgdmlzaXRlIDExN+KCrA0KDQpDQV9tb3llbm5lIDwtIG1lYW4oUkZNMiRDQV9NT1lfVklTSVRFLG5hLnJtID0gVCkNCkNBX21veWVubmUNCkNBX21veWVubmVUQiA8LSBtZWFuKHRyZXNfYm9uJENBX01PWV9WSVNJVEUsIG5hLnJtID0gVCkNCkNBX21veWVubmVUQg0KQ0FfbW95ZW5uZVRCLUNBX21veWVubmUNCmBgYA0KDQojIyMgUGVyaW9kaXF1ZQ0KDQpgYGB7cn0NCiMgZGVwZW5zZSBtb3llbm5lIHN1ciBsYSBwZXJpb2RlDQoNCm10X21veWVubmUgPC0gbWVhbihSRk0kTU9OVEFOVF9DVU1VTEUsbmEucm0gPSBUKQ0KbXRfbW95ZW5uZQ0KDQptdF9tb3llbm5lVEIgPC0gbWVhbih0cmVzX2JvbiRNT05UQU5UX0NVTVVMRSxuYS5ybSA9IFQpDQptdF9tb3llbm5lVEINCg0KbXRfbW95ZW5uZVRCLW10X21veWVubmUNCmBgYA0KDQpMZXMgdHLDqHMgYm9uIGNpZW50cyBjdW11bGVudCBwbHVzIGRlIGTDqXBlbnNlcyBtYWxncsOpIGRlcyBkw6lwZW5zZXMgaW5mw6lyaWV1cmVzIMOgIGxhIG1veWVubmUgcGFyIHBhc3NhZ2UgKGNhciBwbHVzIGRlIHBhc3NhZ2UgZW4gdG91dCkuDQoNCiMjIyBBZ2UNCg0KYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9DQojIGRlcGVuc2UgbW95ZW5uZSBzdXIgbGEgcGVyaW9kZSBlbiBmb25jdGlvbiBkZSBsJ2FnZQ0KDQp0YWI9ZGF0YS5mcmFtZShSRk0yJEFHRSxSRk0yJE1PTlRBTlRfQ1VNVUxFKQ0KdGFiPW5hLm9taXQodGFiKQ0KdGFiVEI9ZGF0YS5mcmFtZSh0cmVzX2JvbiRBR0UsdHJlc19ib24kTU9OVEFOVF9DVU1VTEUpDQp0YWJUQj1uYS5vbWl0KHRhYlRCKQ0KDQpncm91cGVfYWdlPWN1dCh0YWIkUkZNMi5BR0UsYnJlYWtzID0gYygwLDE1LDIwLDI1LDMwLDM1LDQwLDQ1LDUwLDU1LDYwLDY1LDcwLDc1LDkwKSkNCmdyb3VwZV9hZ2VUQj1jdXQodGFiVEIkdHJlc19ib24uQUdFLGJyZWFrcyA9IGMoMCwxNSwyMCwyNSwzMCwzNSw0MCw0NSw1MCw1NSw2MCw2NSw3MCw3NSw5MCkpDQp0YWI9ZGF0YS5mcmFtZSh0YWIsZ3JvdXBlX2FnZSkNCnRhYlRCPWRhdGEuZnJhbWUodGFiVEIsIGdyb3VwZV9hZ2VUQikNCg0KbmFtZXModGFiKT1jKCdhZ2UnLCdtb250YW50X2N1bXVsZScsIkludGVydmFsbGVfYWdlIikNCm5hbWVzKHRhYlRCKT1jKCdhZ2UnLCdtb250YW50X2N1bXVsZScsIkludGVydmFsbGVfYWdlIikNCg0Kc3VtbWFyeSh0YWJUQiRJbnRlcnZhbGxlX2FnZSkNCg0KVDQwXzUwPWZpbHRlcih0YWIsSW50ZXJ2YWxsZV9hZ2U9PSIoNDAsNDVdIikNCnN1bShUNDBfNTAkbW9udGFudF9jdW11bGUpDQoNCg0KZ2dwbG90KHRhYikrYWVzKHg9SW50ZXJ2YWxsZV9hZ2UsY29sPW1vbnRhbnRfY3VtdWxlLCBmaWxsPUludGVydmFsbGVfYWdlKStnZW9tX2JhcigpK2xhYnModGl0bGU9IlJlcGFydGl0aW9uIGR1IENBIHBhciBncm91cGUgZCdhZ2UiLCB4PSJhZ2UiLCB5PSJFZmZlY3RpZiIpDQpnZ3Bsb3QodGFiVEIpK2Flcyh4PUludGVydmFsbGVfYWdlLGNvbD1tb250YW50X2N1bXVsZSwgZmlsbD1JbnRlcnZhbGxlX2FnZSkrZ2VvbV9iYXIoKStsYWJzKHRpdGxlPSJSZXBhcnRpdGlvbiBkZXMgdHJlcyBib24gY2xpZW50cyBwYXIgZ3JvdXBlIGQnYWdlIiwgeD0iYWdlIiwgeT0iRWZmZWN0aWYiKQ0KDQpnZ3Bsb3QoZGF0YT1SRk0yLCBhZXMoeD1UWVBPLCB5PU1PTlRBTlRfQ1VNVUxFLCBmaWxsPVRZUE8pKSArDQogIGdlb21fYmFyKGFlcyh5ID0gKC4uY291bnQuLikvc3VtKC4uY291bnQuLiksIHN0YXQ9ImlkZW50aXR5IikpKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTcGVjdHJhbCIpKw0KICBsYWJzKHg9IlR5cG9sb2dpZXMiLCB5PSJDQSIsIHRpdGxlPSJSw6lwYXJ0aW9uIGR1IENBIikNCg0Kc3VtbWFyeSh0YWIpDQpzdW1tYXJ5KHRhYlRCKQ0KYGBgDQoNCiMgTG9jYWxpc2F0aW9uIC0gZ3JhcGhzDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQ0KI2xvY2FsaXNhdGlvbg0KDQpzdW1tYXJ5KFJGTSRSRUdJT05TKQ0KMTE4NDAvKDI0MTEzKzExODQwKQ0KMjQxMTMvKDI0MTEzKzExODQwKQ0KOTgwLyg5ODArMjA1MykNCjIwNTMvKDk4MCsyMDUzKQ0KDQojMzU5NTUgY2xpZW50cywgMzI1MyB0cmVzIGJvbg0KDQoNCnR5cG88LSBnZ3Bsb3QoUkZNMikgKw0KICBhZXMoeD1UWVBPLGNvbD1UWVBPLCBmaWxsPVRZUE8pICsNCiAgZ2VvbV9iYXIoYWVzKHkgPSAoLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSxmaWxsPVRZUE8pKQ0KDQp0eXBvICsNCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNwZWN0cmFsIikgKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTcGVjdHJhbCIpICsNCiAgbGFicyh5PSJQcm9wb3J0aW9uIiwgeD0iVHlwb2xvZ2llIiwgdGl0bGU9IlJlcGFydGl0aW9uIGRlcyBjbGllbnRzIGFwcmVzIFJGTSIpICMrIA0KICAjZ2VvbV90ZXh0KGFlcyhsYWJlbD1sZW4pLCB2anVzdD0xLjYsIGNvbG9yPSJ3aGl0ZSIsIHNpemU9My41KQ0KDQpzdW1tYXJ5KFJGTTIkVFlQTykNCg0KZ2dwbG90KGRhdGE9UkZNMiwgYWVzKHg9VFlQTywgeT1NT05UQU5UX0NVTVVMRSwgZmlsbD1UWVBPKSkgKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTcGVjdHJhbCIpKw0KICBsYWJzKHg9IlR5cG9sb2dpZXMiLCB5PSJDQSIsIHRpdGxlPSJSw6lwYXJ0aW9uIGR1IENBIikNCg0KDQozMjUwKzc5Nis4NjYrOTgwKzE4MjkrODc0NSsxOTQ4OQ0KMzI1MC8zNTk1NQ0KNzk2LzM1OTU1DQo4NjYvMzU5NTUNCjk4MC8zNTk1NQ0KMTkyOC8zNTk1NQ0KODc0NS8zNTk1NQ0KMTk0ODkvMzU5NTUNCjkuMSsyLjIrMi40KzIuMys1LjQrMjQuNCs1NC4yDQoNCg0KI2luc3RhbGwucGFja2FnZXMoInBsb3RyaXgiKQ0KbGlicmFyeShwbG90cml4KQ0KVHlwb0MgPC0gUkZNMiU+JSBzZWxlY3QoVFlQTykgDQoNCnN1bW1hcnkoVHlwb0MpDQoNCng9YygzMjUwLCA3OTYsIDg2NiwgOTgwLCAxODI5LCA4NzQ1LCAxOTQ4OSkNCnRvdCA8LSAzMjUwKzc5Nis5ODArMTgyOSs4NzQ1KzE5NDg5DQozMjUwL3RvdA0KNzk2L3RvdA0KODY2L3RvdA0KOTgwL3RvdA0KMTgyOS90b3QNCjg3NDUvdG90DQoxOTQ4OS90b3QNCjkuMjYrMi4yNisyLjQ2KzIuNzkrNS4yMSsyNC45Mis1NS41NA0KbGJscyA8LSBjKCJUUkVTIEJPTlMiLCJCT05TIiwiUEVSVEVTIiwiUEVUSVRTIiwiRkFJQkxFUyIsIk5PVVZFQVVYIiwiSU5BQ1RJRlMiKQ0KcGllM0QoeCwgbGFiZWxzPWxibHMsIGV4cGxvZGU9MC4xLCBtYWluPSJUeXBvbG9naWVzIGRlcyBjbGllbnRzIiwgY29sID0gYygicmVkIiwgImRhcmtnb2xkZW5yb2QzIiwgImRhcmtnb2xkZW5yb2QxIiwgInllbGxvdyIsICJ5ZWxsb3dncmVlbiIsICJzZWFncmVlbjQiLCAicm95YWxibHVlNCIpKQ0KIyMgc3RhdCBiaS12YXJpw6llcw0KYGBgDQoNCiMgQ2xpZW50IHR5cGUgVHJlcyBCb24NCg0KIyMgQWdlDQoNCmBgYHtyfQ0KYWdlPXRyZXNfYm9uJEFHRQ0KbWVhbihhZ2UsbmEucm0gPSBUKQ0KYGBgDQoNCiMjIExvY2FsaXNhdGlvbg0KDQpgYGB7cn0NCiMgbG9jYWxpc2F0aW9uIGNsaWVudA0KdGFibGUodHJlc19ib24kUkVHSU9OUykNCmdncGxvdChkYXRhID0gdHJlc19ib24pK2Flcyh4PVJFR0lPTlMpK2dlb21fYmFyKCkNCmBgYA0KDQojIyBEZXBlbnNlIE1veWVubmUNCg0KIyMjIFBhciBWaXNpdGUNCg0KYGBge3J9DQojIGRlcGVuc2UgbW95ZW5uZSBwYXIgdmlzaXRlIDExN+KCrA0KbWVhbih0cmVzX2JvbiRDQV9NT1lfVklTSVRFLG5hLnJtID0gVCkNCmBgYA0KDQojIyMgUGVyaW9kaXF1ZQ0KDQpgYGB7cn0NCiMgZGVwZW5zZSBtb3llbm5lIHN1ciBsYSBwZXJpb2RlDQpwYXN0ZSgiTW9udGFudCBjdW11bGU6Iixyb3VuZChtZWFuKHRyZXNfYm9uJE1PTlRBTlRfQ1VNVUxFLG5hLnJtID0gVCksMikpDQpwYXN0ZSgiTm1iIGRlIHZpc2l0ZToiLHJvdW5kKG1lYW4odHJlc19ib24kTkJfVklTSVRFLG5hLnJtID0gVCksMCkpDQpwYXN0ZSgiRGVwZW5zZSBtb3llbm5lIHBhciB2aXNpdGU6Iiwgcm91bmQobWVhbih0cmVzX2JvbiRNT05UQU5UX0NVTVVMRSxuYS5ybSA9IFQpL21lYW4odHJlc19ib24kTkJfVklTSVRFLG5hLnJtID0gVCksMikpDQpnZ3Bsb3QoUkZNMikrYWVzKHg9VFlQTyxjb2w9VFlQTykrZ2VvbV9iYXIoYWVzKHkgPSAoLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSxmaWxsPVRZUE8pKSt4bGFiKCJ0eXBvbG9naWUiKSt5bGFiKCJwcm9wb3J0aW9uIikNCmBgYA0KDQoNCiMjIFBsb19seQ0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiNpbnN0YWxsLnBhY2thZ2VzKCdQbG90X2x5JykNCmxpYnJhcnkocGxvdGx5KQ0KDQpUeXBvPXVuaXF1ZShSRk0yJFRZUE8pDQpUeXBvDQpkZj1kYXRhLmZyYW1lKCkNCmRmX2ZpbmFsPWRhdGEuZnJhbWUoKQ0KZm9yIChpIGluIFR5cG8pew0KICBkZj1SRk0yJT4lIGZpbHRlcihUWVBPPT1pKSAlPiUgc3VtbWFyaXNlKG1veV9Nb250YW50X0N1bXVsZT1tZWFuKE1PTlRBTlRfQ1VNVUxFLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW95X05CX1Zpc2l0ZT1tZWFuKE5CX1ZJU0lURSxuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1veV9SZWNlbmNlPW1lYW4oUkVDRU5DRSxuYS5ybT1UKSkNCiAgZGZfZmluYWw9cmJpbmQoZGZfZmluYWwsZGYpDQp9DQoNCg0KZGZfZmluYWw9Y2JpbmQoVHlwbyxkZl9maW5hbCkNCg0KVHlwbzNEIDwtIHBsb3RfbHkoZGF0YT1kZl9maW5hbCx4PX5tb3lfTW9udGFudF9DdW11bGUsDQogICAgICAgIHk9fm1veV9OQl9WaXNpdGUsej1+bW95X1JlY2VuY2UsDQogICAgICAgIGNvbG9yPWRmX2ZpbmFsJFR5cG8sIGNvbG9ycyA9IGMoInJlZCIsICJkYXJrZ29sZGVucm9kMyIsICJkYXJrZ29sZGVucm9kMSIsICJ5ZWxsb3ciLCAieWVsbG93Z3JlZW4iLCAic2VhZ3JlZW40IiwgInJveWFsYmx1ZTQiICkpDQpUeXBvM0QNCg0KVHlwbzNEX1RCIDwtIHBsb3RfbHkoZGF0YT1kZl9maW5hbCx4PX5tb3lfTW9udGFudF9DdW11bGUsDQogICAgICAgICAgICAgICAgICAgICB5PX5tb3lfTkJfVmlzaXRlLHo9fm1veV9SZWNlbmNlLA0KICAgICAgICBjb2xvcj1kZl9maW5hbCRUeXBvLCBjb2xvcnMgPSBjKCJyZWQiLCAiZGFya2dyYXkiLCAiZGFya2dyYXkiLCAiZGFya2dyYXkiLCAiZGFya2dyYXkiLCAiZGFya2dyYXkiLCAiZGFya2dyYXkiICkpDQpUeXBvM0RfVEINCg0KYGBgDQoNCg==